package transaction

import (
	"bytes"
	"encoding/gob"
	"errors"
	"fmt"
	"go/types"
	"publicChainSystemTest/block"
	"publicChainSystemTest/tools"
)

/**
 *@author:zhengyilong
 *@email:1797344574@qq.com
 *@phone:13479394730
 *@DateTime:2022/4/18 15:39
 **/

type Transaction struct {
	TXid []byte
	Output []Output
	Input []Input
}

/*
序列化	把目标结构体转成一个有序的序列
	json	xml
*/
func (transaction *Transaction) Serialize() ([]byte,error){
	var result bytes.Buffer
	en := gob.NewEncoder(&result)
	err := en.Encode(transaction)
	if err != nil {
		return nil,err
	}
	return result.Bytes(),nil
}

//创建一个普通交易
func NewTransaction(from, to string, amout uint) (*Transaction,error) {
	bc, err := block.NewBlockChain()
	if err != nil {
		return nil, err
	}

	input := bc.FindAllInput(from)
	output := bc.FindAllOutput(from)
	spendableOutputs := bc.FindSpendOutputs(output, input, amout)
	if spendableOutputs == nil {
		return nil, errors.New("没有可用余额")
	}

	inputs := make([]Input,0)
	for _, output := range spendableOutputs {
		input := NewInput(output.Txid, output.Index, []byte(from))
		inputs = append(inputs,input)
	}

	tx := Transaction{
		Output: nil,
		Input: inputs,
	}
	txBytes, err := tx.Serialize()
	if err != nil {
		return nil,err
	}

	hash := tools.Sha256(txBytes)
	tx.TXid = hash
	return &tx,nil
}

//创建一个Coinbase交易
func NewCoinbase(address string) (*Transaction, error) {
	transaction := Transaction{
		Output: []Output{
			{
				Value:        50,
				ScriptPubKey: []byte(address),
			},
		},
		Input: nil,
	}
	serialize, err := transaction.Serialize()
	if err != nil {
		return nil, err
	}

	transaction.TXid = tools.Sha256(serialize)
	return &transaction,err
}